
#include "meshgenerator.h"
#include <math.h>
#include <string>
#include <sstream>



extern "C"
{
#include "../mesh/triangle.h"
}



MeshGenerator::MeshGenerator(  )
{

}

void 
MeshGenerator::generateMesh( vector<IPoint> _bound, vector<IPoint>& _pts, vector<vector<int> >& _conn  )
{
  int np = (int) _bound.size();

  // get boundary
  struct triangulateio in, out, vorout;

  // points and segments
  in.numberofpoints = np;
  in.pointlist = new double[in.numberofpoints * 2];
  in.numberofsegments = np;
  in.segmentlist = new int[in.numberofpoints * 2];
  in.segmentmarkerlist = NULL;
  double maxL = sqrt( _bound[1].distance2(_bound[0]) );
  double minL = maxL;
  for( int i = 0; i < np; ++i )
  {
    in.pointlist[i*2]   = _bound[i].getX();
    in.pointlist[i*2+1] = _bound[i].getY();
    in.segmentlist[i*2+0] = i;
    in.segmentlist[i*2+1] = i+1;
    double dist2p = sqrt( _bound[i].distance2(_bound[(i+1)%np]) );
    if( minL > dist2p )
      minL = dist2p;
    if( maxL < dist2p )
      maxL = dist2p;
  }
  in.segmentlist[np*2-1] = 0;
  in.numberofpointattributes = 0;
  in.pointattributelist      = (REAL *)NULL;
  in.pointmarkerlist         = (int *)NULL;
  in.numberofholes           = 0;
  in.numberofregions         = 0;
  in.regionlist              = (REAL *)NULL;

  out.pointlist = (REAL *) NULL;             //Not needed if -N switch used. 
  out.pointattributelist = (REAL *) NULL;
  out.pointmarkerlist = (int *) NULL; // Not needed if -N or -B switch used. 
  out.trianglelist = (int *) NULL;          // Not needed if -E switch used. 
  out.triangleattributelist = (REAL *) NULL;
  out.neighborlist = (int *) NULL;         // Needed only if -n switch used. 
  out.segmentlist = (int *) NULL;
  out.segmentmarkerlist = (int *) NULL;
  out.edgelist = (int *) NULL;             // Needed only if -e switch used. 
  out.edgemarkerlist = (int *) NULL;   // Needed if -e used and -B not used. 

  double size = (maxL+minL)/2.0;
  double maxArea = maxL*maxL*sqrt(3.0)/4.0; // equilateral triangle area
  std::ostringstream sstream;
  sstream << maxArea;
  std::string varAsString1 = sstream.str();
  std::string varAsString2 = "pzq30a"+varAsString1+"YiCV";

  // Delaunay Triangulation
  //triangulate();
  triangulate((char *)varAsString2.c_str(), &in, &out, &vorout);

  // checks 
  // get number of points and triangles
  if( out.numberofpoints == 0 || out.numberoftriangles == 0 )
    return;

  // get points
  for( int i = 0; i < out.numberofpoints; ++i )
  {
    IPoint tmp( out.pointlist[i*2+0], out.pointlist[i*2+1], 0.0 );
    _pts.push_back( tmp );
  }

  // get connectivity
  for( int i = 0; i < out.numberoftriangles; ++i )
  {
    vector<int> triang;
    triang.push_back( out.trianglelist[i*3+0] );
    triang.push_back( out.trianglelist[i*3+1] );
    triang.push_back( out.trianglelist[i*3+2] );
    _conn.push_back( triang );
  }

}

